package gui;

import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.EventQueue;

import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JLabel;
import javax.swing.JTabbedPane;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.LayoutStyle.ComponentPlacement;
import java.awt.Color;
import javax.swing.JScrollPane;
import java.util.ArrayList;
import java.util.Random;
import java.awt.event.AdjustmentEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.AdjustmentListener;

import logic.Constantes;
import logic.Pestana;
import logic.analisisSintactico;

import java.awt.Component;
import javax.swing.JButton;
import javax.swing.SwingConstants;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeEvent;

public class MainWindow implements MouseListener, MouseMotionListener,AdjustmentListener,PropertyChangeListener{

	private JFrame 				_Frame;
	private JTabbedPane 		_TabPanelBoard;
	private ArrayList<Block> 	_Tokens;
	private ArrayList<Block>	_Variables;
	private ArrayList<Pestana>  _Pestannas;
	private ArrayList<Board>	_Boards;
	private JScrollPane 		_ScrollPanelTokens;
	private int 				_PressedXEvent;
	private int 				_PressedYEvent;
	private JPanel 				_PanelTokens;
	private JPanel 				_PanelVars;
	private int					_XInicialArrastre;
	private int 				_YInicialArrastre;
	private JComponent			_PanelInicialArrastre;
	private JScrollPane 		_ScrollPanelVars;
	private analisisSintactico  _Analizador;
	private JButton 			_ButtonAddVar;
	private JPanel 				_DebugPanel;
	private JPanel 				_ConfigPanel;

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					MainWindow window = new MainWindow();
					window._Frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the application.
	 */
	public MainWindow() {
		initialize();
	}

	/**
	 * Initialize the contents of the frame.
	 */
	private void initialize() {
		_Frame = new JFrame();
		_Frame.setBounds(100, 100, 787, 513);
		_Frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		_Variables = new ArrayList<Block>();
		_Boards    = new ArrayList<Board>();
		
		_TabPanelBoard = new JTabbedPane(JTabbedPane.TOP);
		
		
		_ScrollPanelTokens = new JScrollPane();
		_ScrollPanelTokens.setBackground(new Color(0, 128, 128));
		
		_ScrollPanelVars = new JScrollPane();
		
		
		GroupLayout groupLayout = new GroupLayout(_Frame.getContentPane());
		groupLayout.setHorizontalGroup(
			groupLayout.createParallelGroup(Alignment.LEADING)
				.addGroup(groupLayout.createSequentialGroup()
					.addContainerGap()
					.addComponent(_ScrollPanelVars, GroupLayout.PREFERRED_SIZE, 131, GroupLayout.PREFERRED_SIZE)
					.addGap(12)
					.addComponent(_TabPanelBoard, GroupLayout.DEFAULT_SIZE, 463, Short.MAX_VALUE)
					.addPreferredGap(ComponentPlacement.RELATED)
					.addComponent(_ScrollPanelTokens, GroupLayout.PREFERRED_SIZE, 131, GroupLayout.PREFERRED_SIZE)
					.addGap(18))
		);
		groupLayout.setVerticalGroup(
			groupLayout.createParallelGroup(Alignment.LEADING)
				.addGroup(groupLayout.createSequentialGroup()
					.addGap(11)
					.addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
						.addGroup(groupLayout.createSequentialGroup()
							.addComponent(_ScrollPanelVars, GroupLayout.DEFAULT_SIZE, 453, Short.MAX_VALUE)
							.addContainerGap())
						.addGroup(groupLayout.createSequentialGroup()
							.addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
								.addComponent(_ScrollPanelTokens, Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, 453, Short.MAX_VALUE)
								.addComponent(_TabPanelBoard, GroupLayout.DEFAULT_SIZE, 453, Short.MAX_VALUE))
							.addGap(11))))
		);
		
		_PanelVars = new JPanel();
		_PanelVars.setAlignmentY(Component.TOP_ALIGNMENT);
		_PanelVars.setAlignmentX(Component.LEFT_ALIGNMENT);
		_PanelVars.setBackground(new Color(0, 128, 128));
		_PanelVars.setPreferredSize(new Dimension(100,140));
		_ScrollPanelVars.add(_PanelVars);
		_ScrollPanelVars.setViewportView(_PanelVars);
		_PanelVars.setLayout(null);
		
		_ButtonAddVar = new JButton("");
		_ButtonAddVar.setPreferredSize(new Dimension(0, 0));
		_ButtonAddVar.setHorizontalTextPosition(SwingConstants.CENTER);
		_ButtonAddVar.addMouseListener(this);
		_ButtonAddVar.setIcon(new ImageIcon(MainWindow.class.getResource("/gui/add.png")));
		_ButtonAddVar.setBounds(20, 90 , 50, 50);
		_PanelVars.add(_ButtonAddVar);
		
		_PanelTokens = new JPanel();
		_PanelTokens.setAlignmentY(Component.TOP_ALIGNMENT);
		_PanelTokens.setAlignmentX(Component.LEFT_ALIGNMENT);
		_PanelTokens.setBackground(new Color(0, 128, 128));
		_ScrollPanelTokens.setViewportView(_PanelTokens);
		_PanelTokens.setLayout(null);
		
		_Frame.getContentPane().setLayout(groupLayout);
		_Analizador = new analisisSintactico();
		_Pestannas = new ArrayList<Pestana>();
		inicializeTokens();
		inicializeVariables();
		inicializeTabs();
		_TabPanelBoard.setSelectedIndex(0);
	}

	private void inicializeTokens(){
		_Tokens    = new ArrayList<Block>();
		for (int i=0 ; i < Constantes.IMAGES.length*Constantes.IMAGES[0].length ; i++){
			_Tokens.add(i, BlockGenerator.createConexion(i/3, i%3));
			_PanelTokens.add(_Tokens.get(i));
			_Tokens.get(i).setBounds(20,20+i*(20+Board.getLabelHeight()),50,50);
			_Tokens.get(i).addMouseMotionListener(this);
			_Tokens.get(i).addMouseListener(this);
			_Tokens.get(i).set_restaurable(true);
			_Tokens.get(i).setType(Block.TOK);
		}
	}
	
	private void inicializeVariables(){
		newVariable();
	}
	
	private void inicializeTabs(){		
		_ConfigPanel = new JPanel();
		_TabPanelBoard.addTab("Config", null, _ConfigPanel, null);
		
		_DebugPanel = new JPanel();
		_TabPanelBoard.addTab("Debug" , null, _DebugPanel, null);
		
		addTab("main");
		addTab("tab1");
		addTab("tab2");
	}
	

	
	private void addTab( String pName ){
		Board board = new Board();
		board.setPreferredSize( new Dimension(1000,1000) );
		board.setBackground(Color.cyan);
		board.setVisible(true);
		
		JScrollPane scrollPanelBoard = new JScrollPane();
		scrollPanelBoard.add(board);
		scrollPanelBoard.setViewportView(board);

		_TabPanelBoard.addTab(pName, null, scrollPanelBoard, null);
		
		JLabel labelShadow = new JLabel("");
		labelShadow.setBounds(0, 0, 0, 0);
		labelShadow.setIcon(new ImageIcon("src/gui/shadow.gif"));
		labelShadow.setBackground(new Color(102, 0, 153));
		labelShadow.setVisible(true);
		board.set_LabelShadow(labelShadow);		

		board.add(labelShadow);
		board.setLayout(null);
		board.addMouseListener(this);
		crearInicio(board);
		_Boards.add(board);
	}
	
	private void crearInicio(Board board){
		Block bloqueInicio  = new Block();
		bloqueInicio.setType(Constantes.TYPE_COMMAND);
		bloqueInicio.setId(Constantes.ID_INICIO);
		bloqueInicio.getAdyacencia();
		_Pestannas.add( new Pestana() );
		_Analizador.addBloque(0, 0, bloqueInicio, _Pestannas.get(0) );
		_Pestannas.get(0).getCasillas()[0][0] = bloqueInicio;
		Block _BlockInicio = BlockGenerator.createinicio();
		board.addLabel(_BlockInicio,0,0);
	}
	
	public void newVariable(){
		Random random = new Random();
		int index = _Variables.size();
		
		_Variables.add(BlockGenerator.createVar());
		_Variables.get(index).setBounds(20,20+index*(20+Board.getLabelHeight()),50,50);
		_Variables.get(index).addMouseMotionListener(this);
		_Variables.get(index).addMouseListener(this);
		_Variables.get(index).set_restaurable(true);
		_Variables.get(index).setType(Block.VAR);
		_Variables.get(index).setBackground(Color.getHSBColor(random.nextFloat() , random.nextFloat(), 0.5f));
		_PanelVars.add(_Variables.get(index));
		_PanelVars.setPreferredSize( new Dimension(
				(int)_PanelVars.getPreferredSize().getWidth(),
				(int)_PanelVars.getPreferredSize().getHeight() + 70) );
		System.out.println(_PanelVars.getPreferredSize().toString());
		System.out.println(_PanelVars.getBounds().toString());
		_ScrollPanelVars.getVerticalScrollBar().setValue(_ScrollPanelVars.getVerticalScrollBar().getMaximum());
		_ScrollPanelVars.updateUI();
	}

	@Override
	public void mouseClicked(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseEntered(MouseEvent arg0) {
		// TODO Auto-generated method stub
	}

	@Override
	public void mouseExited(MouseEvent arg0) {
		// TODO Auto-generated method stub
	}

	@Override
	public void mousePressed(MouseEvent evento) {
		// TODO Auto-generated method stub
		if (evento.getComponent().getClass().isInstance( new Block() ) ){
			_Frame.setCursor(Cursor.HAND_CURSOR);
			Block label = (Block)evento.getComponent();
			
			_PressedXEvent = evento.getX();
			_PressedYEvent = evento.getY();
			
			_XInicialArrastre = label.getX();
			_YInicialArrastre = label.getY();
			_PanelInicialArrastre = (JComponent)label.getParent();
			_Frame.getContentPane().add(label,0);
			int x = label.getX() + Board().getX()+_TabPanelBoard.getX()+1;
			int y = label.getY() + Board().getY()+_TabPanelBoard.getY()+1;
			label.setLocation( x , y );
			label.setVisible(false);
			System.out.println(label.getBounds().toString());
		}else if ( evento.getComponent().getClass().isInstance( new JButton() )  ){
			JButton button = (JButton)evento.getComponent();
			button.setLocation(button.getX(), button.getY()+70);
			newVariable();
		}
			
	}

	@Override
	public void mouseReleased(MouseEvent e) {
		// TODO Auto-generated method stub
		if (e.getComponent().getClass().isInstance( new Block() ) ){
			_Frame.setCursor(Cursor.DEFAULT_CURSOR);
			Block label = (Block)e.getComponent();	
			label.setVisible(true);
			Board().add(label,0);
			if ( Board().getMousePosition(true) != null){
				int row = Math.round((float)(label.getX() - _TabPanelBoard.getX() - getSelectedScrollPane().getX() - Board().getX() - 1)
						/(float)Board.getLabelHeight());
				int col = Math.round((float)(label.getY() - _TabPanelBoard.getY() - getSelectedScrollPane().getY() - Board().getY() - 1)
						/(float)Board.getLabelWidth());
				System.out.println( row );
				System.out.println( col );
				label.setType(Constantes.TYPE_PIPES_SPACE);
				label.setId(5);
				if ( _Analizador.addBloque(row,col , label, _Pestannas.get(0)) ){
					System.out.println( "true" );
					label.setLocation(row*Board.getLabelHeight(),col*Board.getLabelWidth());
					if (label.is_restaurable()){
						restaurar(label);
					}
				}else{
					Block block = restaurar(label);
					if ( _PanelInicialArrastre.equals( Board() ) ){
						block.set_restaurable(false);
					}
					label.getParent().remove(label);					
				}
			}else{
				Block block = restaurar(label);
				if ( _PanelInicialArrastre.equals( Board() ) ){
					block.set_restaurable(false);
				}
				label.getParent().remove(label);
			}
			Board().get_LabelShadow().setVisible(false);
			_Frame.repaint();
			System.out.println("RELEASED");
			_Pestannas.get(0).recorrer();
		}
	}
	
	public Block restaurar( Block pBlock ){
		Block restoredBlock = new Block();
		_PanelInicialArrastre.add(restoredBlock);
		restoredBlock.setBounds(this._XInicialArrastre, this._YInicialArrastre ,Board.getLabelWidth(), Board.getLabelHeight() );
		restoredBlock.setIcon(pBlock.getIcon());
		restoredBlock.addMouseListener(this);
		restoredBlock.addMouseMotionListener(this);
		restoredBlock.set_restaurable(true);
		restoredBlock.setType(pBlock.getType());
		restoredBlock.setBackground(pBlock.getBackground());
		pBlock.set_restaurable(false);	
		restoredBlock.repaint();
		return restoredBlock;
	}

	@Override
	public void mouseDragged(MouseEvent e) {
		Block label = (Block)e.getComponent();
		label.setVisible(true);
		label.setLocation(
				e.getX() + label.getX() - _PressedXEvent,
				e.getY() + label.getY() - _PressedYEvent);
		System.out.println(label.getBounds().toString());
		Board().get_LabelShadow().setBounds(
				Math.round((float)(label.getX() - _TabPanelBoard.getX() - getSelectedScrollPane().getX() - Board().getX() - 1)
						/(float)Board.getLabelHeight())*Board.getLabelHeight(),
				Math.round((float)(label.getY() - _TabPanelBoard.getY() - getSelectedScrollPane().getY() - Board().getY() - 1)
						/(float)Board.getLabelWidth())*Board.getLabelWidth(),
				Board.getLabelWidth(),Board.getLabelHeight()
		);
		Board().get_LabelShadow().setVisible(true);
		_Frame.repaint();
	}

	@Override
	public void mouseMoved(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void adjustmentValueChanged(AdjustmentEvent e) {
		// TODO Auto-generated method stub
		_Frame.repaint();
	}

	@Override
	public void propertyChange(PropertyChangeEvent evt) {
	}
	
	public Board Board(){
		System.out.println(_Boards);
		System.out.println(_TabPanelBoard);
		return _Boards.get(_TabPanelBoard.getSelectedIndex()-2);
	}
	
	public JScrollPane getSelectedScrollPane(){
		return (JScrollPane)_TabPanelBoard.getSelectedComponent();
	}
}
